<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

include_once 'kirey.php';
include_once 'lala.php';
include_once 'stemmer.php';
include_once 'missparse.php';

/**
 * Description of inv_file
 *
 * @author Albadr
 */
class Inv_file extends CI_Model {

    function __construct() {
        parent::__construct();
    }
    
    public function computeQueryWeight($queries,$options,&$invertedFile){
        $terms = Array();
        
        if ($options["stop"] == "yes") {
            /*loading file stop word */
            $miss_parse = new missparse();
            $stop_words = $miss_parse->parse_common_words_to_regex(base_url()."upload/stop.words");
        }
        
        if (!is_array($queries)) $queries = Array(1=>$queries);
        
        foreach ($queries as $query) {
            if ($options["stop"] == "yes") {
                /* Memecah kata per kata di title dan konten, stopwords deleted */
                $queryTerms = explode(" ", $miss_parse->remove_common_words_from_regex($query->query, $stop_words));
            }else{
                $queryTerms = explode(" ", $query->query);
            }
            
            foreach ($queryTerms as $term) {
                if ($term != '') {
                    if ($options["stem"] == "yes") {
                        /* Stemm the term */
                        $term = PorterStemmer::Stem($term);
                    }

                    if (!isset($terms[$query->no][$term])) {
                        $terms[$query->no][$term] = new Lala($term);
                    }
                    
                    $terms[$query->no][$term]->rawtf++;
                }
            }
            unset ($queryTerms);
        }
        /* Menghitung tf tiap term per query, masukkan ke weight */
        if ($options["tf"] == "raw") {
            foreach ($terms as $termsOnOneQuery) {
                foreach ($termsOnOneQuery as $oneterm)
                    $oneterm->weight = (!isset($oneterm->rawtf) || $oneterm->rawtf == 0) ? 0 : $oneterm->rawtf;
            }
        } else if ($options["tf"] == "log") {
            foreach ($terms as $termsOnOneQuery) {
                foreach ($termsOnOneQuery as $oneterm)
                    $oneterm->weight = (!isset($oneterm->rawtf) || $oneterm->rawtf == 0) ? 0 : log10($oneterm->rawtf[$i]) + 1;
            }
        } else if ($options["tf"] == "bin") {
            foreach ($terms as $termsOnOneQuery) {
                foreach ($termsOnOneQuery as $oneterm)
                    $oneterm->weight = (!isset($oneterm->rawtf) || $oneterm->rawtf == 0) ? 0 : 1;
            }
        } else if ($options["tf"] == "aug") {
            foreach ($terms as $termsOnOneQuery) {
                $maxtf = 1;//max($oneterm->rawtf); /*Masih meragukan*/
                foreach ($termsOnOneQuery as $oneterm){
                    $oneterm->weight = (!isset($oneterm->rawtf) || $oneterm->rawtf == 0) ? 0.5 : 0.5 + 0.5 * $oneterm->rawtf / $maxtf;
                    unset($maxtf);
                }
            }
        }
        
        
        /* Jika idf ada di option, mengalikan idf pada weight tiap term dalam query*/
        if ($options["idf"] == "yes") {
            foreach ($terms as $termsOnOneQuery) {
                foreach ($termsOnOneQuery as $oneterm){
                    $idf = isset($invertedFile[$oneterm->the_term]->idf) ? $invertedFile[$oneterm->the_term]->idf : 0;
                    $oneterm->weight = $idf;
                    $oneterm->weight = $oneterm->weight * $idf;
                }
            }
        }

        /* Jika normalisasi ada di option, mengalikan normalisasi pada weight tiap term dalam query */
        if ($options["norm"] == "yes") {
            foreach ($terms as $termsOnOneQuery) {
                $array = Array();
                foreach ($termsOnOneQuery as $oneterm){
                    $array[] = $oneterm->weight*$oneterm->weight;
                }
                $EUC = sqrt(array_sum($array));
                unset($array);
                foreach ($termsOnOneQuery as $oneterm){
                    $oneterm->weight = $EUC==0 ? 0 :$oneterm->weight / $EUC;
                }
            }
        }

        return $terms;
    }

    /**
     * Memmbuat inverted file dari array dokumen yang ada.
     * Inverted file yang dikembalikan terdiri dari array keterangan tiap term,
     * dengan keterangannya adalah properti pada objek Kirey.
     * @param type $docs
     * @param type $options berisi lima kunci, "tf" untuk tipe tf {"raw","log","aug","bin"},
     * "idf" untuk pengaturan penggunaan idf atau tidak,
     * "norm" untuk pengaturan penggunaan normalisasi atau tidak,
     * "stop" untuk pengaturan penggunaan pemangkasan stopwords atau tidak, dan
     * "stem" untuk pengaturan penggunaan stemmer atau tidak.
     * @todo: implementasi opsi stop, dan pengujian opsi stem == yes
     * @return Array of Kirey 
     */
    public function generate($docs, $options) {
        $terms = Array();
        $DOC_COUNT = sizeof($docs);
        
        if ($options["stop"] == "yes") {
            /*loading file stop word */
            $miss_parse = new missparse();
            $stop_words = $miss_parse->parse_common_words_to_regex(base_url()."upload/stop.words");
        }
        
        foreach ($docs as $doc) {
            /* ADD CODE TO KILL STOPWORDS HERE */
            if ($options["stop"] == "yes") {
                /* Memecah kata per kata di title dan konten, stopwords deleted */
                $titleTerms = explode(" ", $miss_parse->remove_common_words_from_regex($doc->title, $stop_words));
            } else {
                /* Memecah kata per kata di title dan konten, stopwords included */
                $titleTerms = explode(" ", $doc->title);
            }
            
            /* Mendata kata-kata di title */
            foreach ($titleTerms as $term) {
                if ($term != '') {
                    if ($options["stem"] == "yes") {
                        /* Stemm the term */
                        $term = PorterStemmer::Stem($term);
                    }

                    if (!isset($terms[$term])) {
                        $terms[$term] = new Kirey($term);
                    }
                    
                    $terms[$term]->position[$doc->no] = true;
                    if (!isset($terms[$term]->rawtf[$doc->no]))
                        $terms[$term]->rawtf[$doc->no] = 1;
                    else
                        $terms[$term]->rawtf[$doc->no]++;
                }
            }
            unset ($titleTerms);
            
            if ($options["stop"] == "yes") {
                /* Memecah kata per kata di title dan konten, stopwords deleted */
                $contentTerms = explode(" ", $miss_parse->remove_common_words_from_regex($doc->content, $stop_words));
            } else {
                /* Memecah kata per kata di title dan konten, stopwords included */
                $contentTerms = explode(" ", $doc->content);
            }

            /* Mendata kata-kata di body */
            foreach ($contentTerms as $term) {
                if ($term != '') {
                    /* ADD CODE TO KILL STOPWORDS HERE */

                    if ($options["stem"] == "yes") {
                        /* Stemm the term */
                        $term = PorterStemmer::Stem($term);
                    }

                    if (!isset($terms[$term])) {
                        $terms[$term] = new Kirey($term);
                    }
                    $terms[$term]->position[$doc->no] = true;
                    if (!isset($terms[$term]->rawtf[$doc->no]))
                        $terms[$term]->rawtf[$doc->no] = 1;
                    else
                        $terms[$term]->rawtf[$doc->no]++;
                }
            }
            unset ($contentTerms);
            unset ($doc);
        }
        
        if ($options["stop"] == "yes"){
            unset($stopwords); 
            unset($miss_parse);
        }
        /* Menghitung df tiap term */
        foreach ($terms as $oneterm) {
            $oneterm->df = sizeof($oneterm->position);
            unset($oneterm->position);
        }

        /* Menghitung tf tiap term per dokumen, masukkan ke weight */
        if ($options["tf"] == "raw") {
            foreach ($terms as $oneterm) {
                for ($i = 1; $i <= $DOC_COUNT; $i++) {
                    $oneterm->weight[$i] = (!isset($oneterm->rawtf[$i])) ? 0 : $oneterm->rawtf[$i];
                }
                unset($oneterm->rawtf);
            }
        } else if ($options["tf"] == "log") {
            foreach ($terms as $oneterm)
                for ($i = 1; $i <= $DOC_COUNT; $i++) {
                    $oneterm->weight[$i] = (!isset($oneterm->rawtf[$i]) || $oneterm->rawtf[$i] == 0) ? 0 : log10($oneterm->rawtf[$i]) + 1;
                }
        } else if ($options["tf"] == "bin") {
            foreach ($terms as $oneterm)
                for ($i = 1; i <= $DOC_COUNT; $i++) {
                    $oneterm->weight[$i] = (!isset($oneterm->rawtf[$i]) || $oneterm->rawtf[$i] == 0) ? 0 : 1;
                }
        } else if ($options["tf"] == "aug") { /*Masih meragukan*/
            foreach ($terms as $oneterm) {
                $maxtf = max($oneterm->rawtf);
                for ($i = 1; $i <= $DOC_COUNT; $i++) {
                    $oneterm->weight[$i] = (!isset($oneterm->rawtf[$i]) || $oneterm->rawtf[$i] == 0) ? 0.5 : 0.5 + 0.5 * $oneterm->rawtf[$i] / $maxtf;
                }
                unset($maxtf);
            }
        }
              
        /* Jika idf ada di option, mengalikan idf pada weight tiap term per dokumen */
        if ($options["idf"] == "yes") {
            foreach ($terms as $oneterm) {
                $idf = log10($DOC_COUNT / $oneterm->df);
                for ($i = 1; $i <= $DOC_COUNT; $i++) {
                    $oneterm->weight[$i] = $oneterm->weight[$i] * $idf;
                }
                $oneterm->idf = $idf;
                unset($idf);
            }
        }
        
        /* Jika normalisasi ada di option, mengalikan normalisasi pada weight tiap term per dokumen */
        if ($options["norm"] == "yes") {
            $EUC = Array();
            for ($i = 1; $i <= $DOC_COUNT; $i++) {
                $array = Array();
                foreach ($terms as $oneterm) {
                    $array[] = $oneterm->weight[$i]*$oneterm->weight[$i];
                }
                $EUC[$i] = sqrt(array_sum($array));
                unset($array);
            }
            foreach ($terms as $oneterm) {
                for ($i = 1; $i <= $DOC_COUNT; $i++) {
                    $oneterm->weight[$i] = $EUC[$i]==0 ? 0 : $oneterm->weight[$i] / $EUC[$i];
                }
            }
        }

        return $terms;
    }

    /**
     * Menghitung akar pangkat dua dari penjumlahan kuadrat tiap elemen dalam array
     * @param type $array 
     */
    private function _eucDistance($array) {
        $arrayKuadrat = Array();
        foreach ($array as $elem) {
            $arrayKuadrat[] = $elem * $elem;
        }

        return sqrt(array_sum($arrayKuadrat));
    }

}

?>
